-
-
Notifications
You must be signed in to change notification settings - Fork 10
fix: keyword list parsing crash #56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
fix: keyword list parsing crash #56
Conversation
lib/spitfire.ex
Outdated
| parser = parser |> next_token() |> next_token() | ||
| {item, parser} = parse_expression(parser, @kw_identifier, true, false, false) | ||
| {item, parser} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i believe this case actually should result in an error,
iex(1)> Code.string_to_quoted("[foo: \"bar\", :baz]")
{:error,
{[line: 1, column: 12],
"unexpected expression after keyword list. Keyword lists must always come last in lists and maps. Therefore, this is not allowed:\n\n [some: :value, :another]\n %{some: :value, another => value}\n\nInstead, reorder it to be the last entry:\n\n [:another, some: :value]\n %{another => value, some: :value}\n\nSyntax error after: ",
"','"}}
| code = ~S''' | ||
| defmodule MyModule do | ||
| IO.inspect( | ||
| :stderr, | ||
| label: "label", | ||
| (__cursor__()) | ||
| ) | ||
| end | ||
| ''' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is an interesting result from the builtin parser
iex(5)> Code.string_to_quoted(~S'''
...(5)> defmodule MyModule do
...(5)> IO.inspect(
...(5)> :stderr,
...(5)> label: "label",
...(5)> (__cursor__())
...(5)> )
...(5)> end
...(5)> ''')
{:ok,
{:defmodule, [line: 1],
[
{:__aliases__, [line: 1], [:MyModule]},
[
do: {{:., [line: 2], [{:__aliases__, [line: 2], [:IO]}, :inspect]},
[line: 2], [:stderr, [{:label, "label"}, {:__cursor__, [line: 5], []}]]}
]
]}}
iex(6)> Code.string_to_quoted(~S'''
...(6)> defmodule MyModule do
...(6)> IO.inspect(
...(6)> :stderr,
...(6)> label: "label",
...(6)> :foo
...(6)> )
...(6)> end
...(6)> '''
...(6)> )
{:error,
{[line: 4, column: 19],
"unexpected expression after keyword list. Keyword lists must always come as the last argument. Therefore, this is not allowed:\n\n function_call(1, some: :option, 2)\n\nInstead, wrap the keyword in brackets:\n\n function_call(1, [some: :option], 2)\n\nSyntax error after: ",
"','"}}
iex(7)>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either the builtin parser supports a macro call returning tuple AST node or this is an error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another possibility it is more forgiving for nodes with __cursor__() special form
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mhanberg We have two options here.
- Have a special handling for
__cursor__()nodes in keyword lists - Make the parser error tolerant and either silently drop invalid list entries or produce invalid AST
b169652 to
41c96eb
Compare
|
I was trying to integrate Spitfire into Expert and run into the same issue this PR is trying to fix, triggered by code like |
Add test cases from elixir-tools#32
41c96eb to
a0842be
Compare
| @tag foo: bar, | ||
| foo | ||
| """ | ||
|
|
||
| assert Spitfire.parse(code) == | ||
| { | ||
| :ok, | ||
| {:@, [end_of_expression: [newlines: 1, line: 2, column: 6], line: 1, column: 1], | ||
| [ | ||
| {:tag, [line: 1, column: 2], | ||
| [[{:foo, {:bar, [line: 1, column: 11], nil}}, {:foo, [line: 2, column: 3], nil}]]} | ||
| ]} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for taking a year to dive into this more.
Shouldn't this be an error in this case?
Fixes crash 3 from #48
Fixes #26
Supersedes #32